import Protocol from './protocol/Protocol';
import defaultConfig from './config';
import { ErrorEvents, MessageType, MessageEvents, ProtocolEvent } from './constants';
import { toObject } from './utils';

export * from './constants';

export { CONN_STATUS } from './protocol/Protocol';

export default class IM extends Protocol {
  configs = {};

  constructor(configs) {
    super(configs);
    this.validConf(configs);
    this.configs = configs;
  }

  validConf(config) {
    Object.keys(config).forEach((key) => {
      const isEmptyString = config[key] === '';
      const isUndefined = config[key] === undefined;
      if (isEmptyString || isUndefined) {
        console.warn(`config.${key}:`, config[key]);
      }
    });
  }

  /**
   * 连接im
   * @param bizUserType 业务用户类型:
   *  VENDOR-供应商，STORE-门店，
   *  MEMBER-会员(消费者)，
   *  KYLIN-麒麟内部用户
   * @param bizUserKey 业务用户登录令牌
   * @param configs 补充配置
   * @return {IM}
   */
  static connect(bizUserType, bizUserKey, configs = {}, isAuth) {
    const im = new IM({ ...defaultConfig, ...configs, isAuth });
    im.connect(bizUserType, bizUserKey, true);
    im.$listen();
    return im;
  }

  /**
   * 发送信息
   * @param msgType 消息类型
   */
  async sendMessage(cmd, data = {}) {
    return await super.sendMessage(cmd, data);
  }

  /**
   * 收到下行信息
   * @param fn
   */
  onMessage(fn) {
    this.$on(MessageEvents.RECEIVED, fn);
  }

  onSystem(fn) {
    this.$on(MessageEvents.SYSTEM, fn);
  }

  /**
   * 所有错误
   * @param fn
   */
  onError(fn) {
    // 协议层错误
    // this.$on(ErrorEvents.PROTOCOL_ERROR, fn);
    // 业务层错误
    this.$on(ErrorEvents.CONNECTION_ERROR, fn);
  }

  /**
   * 监听连接事件
   * @param fn
   */
  onConnect(fn) {
    super.onConnect(fn);
  }

  /**
   * 连接状态改变
   * @param fn
   */
  onConnStateChange(fn) {
    this.$on(ProtocolEvent.CONN_STATE_CHANGE, fn);
  }

  /**
   * 消息发送成功时触发
   * @param fn
   */
  onDeliverMessage(fn) {
    this.$on(ProtocolEvent.DELIVER_MESSAGE, fn);
  }

  /**
   * 监听下层行为
   */
  $listen() {
    super.onReceiveMessage((message) => {
      this.$emit(MessageEvents.RECEIVED, message);
    });
  }
}
